package com.xiang.sql.service;

import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiang.api.Util;
import com.xiang.api.service.WxService;
import com.xiang.sql.StaticSql;
import com.xiang.sql.entity.Group;
import com.xiang.sql.entity.Order;
import com.xiang.sql.entity.Prize;
import com.xiang.sql.entity.PrizeGroup;
import com.xiang.sql.entity.Transfer;
import com.xiang.sql.entity.User;
import com.xiang.sql.mapper.TransferMapper;

import jakarta.annotation.Resource;

/**
 * 转账 服务实现类
 * 
 * @author mac-xiang
 */
@Service
public class TransferService extends ServiceImpl<TransferMapper, Transfer> {
  @Resource
  TransferMapper mapper;

  @Autowired
  WxService wxService;

  private QueryWrapper<Transfer> readWrapper(JSONObject p, User per) {
    QueryWrapper<Transfer> ret = Util.getQuery(p, Transfer.class);
    if (per != null && !per.per("转账查询")) {
      ret.eq("`create`", per.id);
    }
    return ret;
  }

  private List<Transfer> getList(JSONObject p, User per) {
    return mapper.selectList(readWrapper(p, per));
  }

  private Page<Transfer> getPage(Page<Transfer> page, JSONObject p, User per) {
    return mapper.selectPage(page == null ? new Page<Transfer>(1, 100) : page, readWrapper(p, per));
  }

  /** 转账 */
  private void divideProfits(Transfer e) {
    if (Util.isEmpty(e.name)) {
      e.name = "转账备注为空";
    }
    User user = StaticSql.service.user.getById(e.create);
    if (user != null && !Util.isEmpty(user.wxid)) {
      if (Util.isEmpty(e.id)) {
        e.id = Util.sGetId();
      }
      long money = e.money;
      final int max = 19990;
      if (e.money > 9) {
        while (money > max) {
          e.state = wxService.transfer(e.id, user.wxid, max, e.name, e.des);
          mapper.insert(e);
          money -= max;
          e.id = Util.sGetId();
        }
        if (money > 0) {
          e.state = wxService.transfer(e.id, user.wxid, money, e.name, e.des);
        }
      } else {
        e.state = "金额太小";
      }
      mapper.insert(e);
    }
  }

  private boolean notExist(String type, String oid, String create) {
    List<Transfer> r = mapper.selectList(new QueryWrapper<Transfer>()
        .eq("`type`", type).eq("`oid`", oid).eq("`create`", create));
    final String[] a = { "已完成", "已关闭" };
    r.forEach(e -> {
      if (e.money >= 10 && Util.includes(a, e.state) < 0) {
        refresh(e.id);
      }
    });
    return r.size() == 0;
  }

  /** 各级分润 */
  public String transferOrder(String orderID) {
    Order o = StaticSql.mapper.order.selectOne(new QueryWrapper<Order>().eq("id", orderID));
    if (o == null) {
      throw new RuntimeException("订单id不存在");
    }
    if (!(o.payTime > 0)) {
      throw new RuntimeException("订单未支付");
    }
    Group group = StaticSql.service.group.getById(o.gid);
    if (group == null) {
      group = StaticSql.service.group.getById(0);
    }
    User buy = StaticSql.service.user.getById(o.create),
        u = StaticSql.service.user.getById(group.sid);
    final String mjfl = "买家返利", sjfr = "商家分润", ywtc = "业务提成",
        yjtj = "一级推荐", ejtj = "二级推荐",
        des = String.format("订单: %s", o.id);
    long money = o.money, m = 0,
        rec1 = Long.parseLong(StaticSql.service.setting.getValueById("rec1")),
        rec2 = Long.parseLong(StaticSql.service.setting.getValueById("rec2"));
    // 买家返利
    m = Math.floorDiv(money * buy.commission, 100);
    money -= m;
    if (notExist(mjfl, o.id, buy.id)) {
      divideProfits(new Transfer(mjfl, m, o.id, buy.id, "买家=" + buy.name, des));
    }
    // 商家分润
    m = Math.floorDiv(money * group.commission, 100);
    money -= m;
    if (notExist(sjfr, o.id, group.create)) {
      divideProfits(new Transfer(sjfr, m, o.id, group.create, "商家=" + group.name, des));
    }
    // 业务提成
    m = Math.floorDiv(money * group.salesman, 100);
    money -= m;
    if (notExist(ywtc, o.id, u.id)) {
      divideProfits(new Transfer(ywtc, m, o.id, u.id, "业务=" + u.name, des));
    }
    // 一级推荐
    u = StaticSql.service.user.getById(buy.pid);
    if (u != null) {
      m = Math.floorDiv(money * rec1, 100);
      money -= m;
      if (notExist(yjtj, o.id, u.id)) {
        divideProfits(new Transfer(yjtj, m, o.id, u.id, yjtj + "=" + u.name, des));
      }
      // 二级推荐
      u = StaticSql.service.user.getById(u.pid);
      if (u != null) {
        m = Math.floorDiv(money * rec2, 100);
        money -= m;
        if (notExist(ejtj, o.id, u.id)) {
          divideProfits(new Transfer(ejtj, m, o.id, u.id, ejtj + "=" + u.name, des));
        }
      }
    }

    return "已完成订单分销";
  }

  /** 中奖兑付 */
  public String transferPrize(String prizeGroupID) {
    PrizeGroup prizeGroup = StaticSql.service.prizeGroup.getById(prizeGroupID);
    return transferPrize(prizeGroup);
  }

  private String transferPrize(PrizeGroup prizeGroup) {
    if (prizeGroup == null) {
      throw new RuntimeException("兑奖ID错误");
    }
    if (prizeGroup.user.length() < 1) {
      throw new RuntimeException("该奖品链接未被用户使用");
    }
    if (prizeGroup.cashTime > 0) {
      throw new RuntimeException("该奖品链接已兑付");
    }
    Prize prize = StaticSql.service.prize.getById(prizeGroup.prize);

    return transferPrize(prizeGroup, prize);
  }

  public String transferPrize(PrizeGroup prizeGroup, Prize prize) {
    if (prizeGroup == null) {
      throw new RuntimeException("兑奖ID错误");
    }
    if (prizeGroup.user.length() < 1) {
      throw new RuntimeException("该奖品链接未被用户使用");
    }
    if (prizeGroup.cashTime > 0) {
      throw new RuntimeException("该奖品链接已兑付");
    }
    if (prize == null) {
      throw new RuntimeException("该奖品链接对应奖品不存在");
    }
    Long money = prize.money();
    if (money == null) {
      throw new RuntimeException("该奖品不是现金奖励");
    }
    if (!(money > 0)) {
      throw new RuntimeException("该奖品中奖金额错误");
    }
    divideProfits(new Transfer("中奖兑付", money, prizeGroup.id, prizeGroup.user, prize.name,
        "中奖id: " + prizeGroup.id));
    prizeGroup.group = "0";
    prizeGroup.cashTime = Util.time();
    if (prizeGroup.useTime == 0) {
      prizeGroup.useTime = Util.time();
    }
    StaticSql.service.prizeGroup.updateById(prizeGroup);
    return "已完成中奖兑付";
  }

  /** 其他转账 */
  public String transferOther(Transfer e) {
    divideProfits(e);
    return "已完成其他转账";
  }

  public Object create(JSONObject p, User per) {
    if (per != null && per.per("转账创建")) {
      Transfer entity = Util.getEntity(p, Transfer.class);
      entity.id = Util.sGetId();
      entity.cuid = per.id;
      return transferOther(entity);
    }
    throw new RuntimeException("没有权限");
  }

  public int update(JSONObject p, User per) {
    if (per != null && per.per("转账修改")) {
      Transfer entity = Util.getEntity(p, Transfer.class);
      QueryWrapper<Transfer> qw = Util.getQuery(p, Transfer.class);
      if (this.count(qw) > 10) {
        throw new RuntimeException("单次修改数量超过10条");
      }
      // entity.create = null;
      return mapper.update(entity, qw);
    }
    throw new RuntimeException("没有权限");
  }

  public Object read(JSONObject p, User per) {
    Page<Transfer> page = Util.getPage(p, Transfer.class);
    return page == null ? getList(p, per) : getPage(page, p, per);
  }

  public int delete(JSONObject p, User per) {
    if (per != null && per.per("转账删除")) {
      QueryWrapper<Transfer> q = Util.getQuery(p, Transfer.class);
      if (this.count(q) > 10) {
        throw new RuntimeException("删除数据的数量不能超过10条");
      }
      return mapper.delete(q);
    }
    throw new RuntimeException("没有权限");
  }

  public long count(JSONObject p, User per) {
    return this.count(readWrapper(p, per));
  }

  private void refresh(String id) {
    mapper.update(new UpdateWrapper<Transfer>()
        .eq("id", id).ge("`money`", 10)
        .set("`state`", wxService.QueryTransferStatus(id)));
  }

  public List<Transfer> refresh(JSONObject p, User per) {
    QueryWrapper<Transfer> q = readWrapper(p, per).ge("`money`", 10);
    mapper.selectList(q.clone().notIn("`state`", Arrays.asList("已完成", "已关闭")).select("id")).forEach(e -> {
      refresh(e.id);
    });
    return mapper.selectList(q);
  }
}
